package oldCodePackage;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Random;


public class Game {
	public static final int ALL_TRUMP = 0;
	public static final int CLUBS = 1;
	public static final int DIAMONDS = 2;
	public static final int HEARTS = 3;
	public static final int SPADES = 4;
	public static final int NO_TRUMP = 5;
	
	public static final int JACK = 11;
	public static final int QUEEN = 12;
	public static final int KING = 13;
	public static final int ACE = 1;
	
	public static final Card ACE_OF_HEARTS = new Card(HEARTS, ACE);//used in fingers
	public static final int NUM_CARDS = 52;
	public static final int NIL = 50;
	
	private BufferedReader input = new BufferedReader (new InputStreamReader(System.in)); 
	private Random generator = new Random();
	
	private int numPlayers = 0;
	private int numHumans = 0;
	private int numNPCs = 0;
	
	private Deck deck;
	private Human humans[];
	private NPC NPCs[];
	
	private int scores[];
	private int bid[];
	private int playOrder[];
	private Card hand[];
	
	Game(int numHumans, int numNPCs){
		this.numHumans = numHumans;
		this.numNPCs = numNPCs;
		this.numPlayers = numHumans + numNPCs;
		
		humans = new Human[numHumans];
		for(int i=0; i<numHumans; i++)
			humans[i] = new Human();
		
		NPCs = new NPC[numNPCs];
		for(int i=0; i<numNPCs; i++)
			NPCs[i] = new NPC();
		
		scores = new int[numPlayers];
		bid = new int[numPlayers];
		playOrder = new int[numPlayers];
		
		this.deck = new Deck();
	}
	
	public void playFingers() throws IOException{
		String inStr;
		int menuSel = 1;
		int numToDeal = 0;
		int highestBid, highestBidder;
		boolean doneBidding;
		int bidPlayer;
		int turnPlayer;

		randomizeOrder();

		do{
			do{//start menu
				printScores();
				printMenu();
				inStr = input.readLine();
				menuSel = Integer.parseInt(inStr); 
			}while(menuSel != 1 && menuSel !=2); // repeat until valid selection is choosen
			
			if(menuSel == 2)//quit game
				return;
			
			do{
				System.out.println("****************");
				System.out.println("How many cards would you like to deal: ");
				inStr = input.readLine();
				numToDeal = Integer.parseInt(inStr);
			}while(numToDeal < numPlayers  || numToDeal > (NUM_CARDS / numPlayers)); //can only deal valid amounts
			
			//reset for new hand
			deck.shuffleCards();//resets the deck back
			Player.resetCards();//resets bids and hands
			highestBid = -1;
			highestBidder = 0;
			doneBidding = false;
			for(int i=0; i<numPlayers; i++){//reset bids and round scores
				scores[i] = 0;
				bid[i] = 0;
			}
			
			//deal out cards
			for(int i=0; i<numHumans; i++)
				humans[i].receiveHand(deck.dealHand(numToDeal));
			for(int i=0; i<numNPCs; i++)
				NPCs[i].receiveHand(deck.dealHand(numToDeal));
			
			//do all the bidding
			do{
				for(int h=0; h<numPlayers; h++){
					bidPlayer = playOrder[h];
					if(bidPlayer<numHumans){//human player bidding
						if(bidPlayer == highestBidder && highestBid != -1){
							doneBidding = true;
							break;
						}
						
						bid[bidPlayer] = humans[bidPlayer].placeBid();
						if(bid[bidPlayer] > highestBid){
							highestBid = bid[bidPlayer];
							highestBidder = bidPlayer;
						}
					}
					else//npc player
						bid[bidPlayer] = NPCs[bidPlayer].placeBid();
				}
			}while(!doneBidding);
			
			for(int i=0; i<numToDeal; i++){//play cards till they are all gone
				hand = null;
				hand = new Card[numToDeal];//reset hand
				
				for(int j=0; j<numPlayers; j++){//let everyone play one card
					turnPlayer = playOrder[j];
					if(turnPlayer<numHumans)//humans turn to play
						hand[j] = humans[turnPlayer].playCard();
					else//npcs turn to play
						hand[j] = NPCs[turnPlayer].playCard();	
				}
				calcHandWinner();
			}
			
			calcRoundScores();
			calcTotalScores();
			reOrder();
			
		}while(true);
	}
	
	private void reOrder() {
		int lowestScore = scores[0];
		int loser = 0;
		int temp =0; 
		
		for(int i=0; i<numPlayers; i++){//find lowest scorer
			if(lowestScore >= scores[i]){
				lowestScore = scores[i];
				loser = i;
			}
		}
		
		if(playOrder[0] == loser)//dealer lost, just return
			return;
		
		do{//rotate play order until loser is at the position 0
			for(int i=0; i<numPlayers; i++){
				if(i == 0){//special end case
					temp = playOrder[numPlayers-1];
					playOrder[numPlayers-1] = playOrder[0];
				}
				else if(i == numPlayers-1)//special end case 2
					playOrder[i-1] = temp;
				else
					playOrder[i-1] = playOrder[i];
			}
		}while(playOrder[0] != loser);
		
	}

	private void calcTotalScores() {
		for(int i=0; i<numPlayers; i++){
			if(i<numHumans)//human score
				humans[i].addScore(scores[i]);
			else
				NPCs[i].addScore(scores[i]);
		}
		
	}

	private void calcRoundScores() {
		for(int i=0; i<numHumans; i++){//cycle through all human players tricks taken vs bid
			if(humans[i].getTricksBid() == -1)//passed so it doesn't matter
				break;
			else if(humans[i].getTricksTaken() == humans[i].getTricksBid()){//made it exactly so tricks*10 points
				if(humans[i].getTricksBid() == 0)//made a nil
					scores[i] += NIL;
				else
					scores[i] += humans[i].getTricksBid() * 10;
			}
			else if(humans[i].getTricksTaken() > humans[i].getTricksBid()){//took more than bid +/- tricks over*5
				if(humans[i].getTricksBid() == 0)//missed a nil
					scores[i] -= humans[i].getTricksTaken() * 10;
				else{
					scores[i] += humans[i].getTricksBid() * 10;
					adjustAllScores(i, (humans[i].getTricksTaken() - humans[i].getTricksBid())*5);
				}
			}
			else if(humans[i].getTricksTaken() > humans[i].getTricksBid())//took less than bid +/- tricks over*10			
					adjustAllScores(i, (humans[i].getTricksTaken() - humans[i].getTricksBid())*10);
		}
	}

	private void adjustAllScores(int player, int score) {
		for(int i=0; i<numPlayers; i++){
			if(i == player)//negative points
				scores[i] -= score;
			else
				scores[i] += score;
		}
		
	}

	private void calcHandWinner() {
		int currentWinner = 0;
		Card winningCard = hand[0];
		
		for(int i=0; i<numPlayers; i++){//cycle thru all cards for a winner
			if(hand[currentWinner].getSuit() == Player.trumpSuit || hand[currentWinner] == ACE_OF_HEARTS)//trump is winning
				if(winningCard.compareTrump(hand[i]))
					break;
			else if(hand[currentWinner].getSuit() == HEARTS || hand[currentWinner].getSuit() == DIAMONDS)//red suit winning
				if(winningCard.compareRed(hand[i]))
					break;
			else
				if(winningCard.compareBlack(hand[i]))
					break;
			
			winningCard = hand[i];
			currentWinner = i;
		}
		
		if(currentWinner < numHumans) //human won trick
			humans[playOrder[currentWinner]].addTricksTaken();
		else //NPC won trick
			NPCs[playOrder[currentWinner]].addTricksTaken();
	}

	private void printMenu() {
		System.out.println("****************");
		System.out.println("1. Start Game");
		System.out.println("2. Quit");
		System.out.println("Please enter a numer: ");
	}

	private void printScores(){
		System.out.println("**********************************");
		System.out.println("Name \t\t Score");
		System.out.println("~~~~~~~~ \t ~~~~~");
		for(int i=0; i<numHumans; i++)
			System.out.println(humans[i].myName + "\t" + humans[i].getScore());
		
		for(int i=0; i<numNPCs; i++)
			System.out.println(NPCs[i].myName + "\t" + NPCs[i].getScore());
		
		System.out.println("**********************************");
	}
	
	private void randomizeOrder(){
		int randomIndex = 0;
		for(int i=0; i<numPlayers; i++)//reset play order
			playOrder[i] = -1;

		for(int i=0; i<numPlayers; i++){
			do{
				randomIndex = generator.nextInt(numPlayers);
			}while(playOrder[randomIndex] != -1);//do until an empty spot is found
			
			playOrder[randomIndex] = i;
		}
	}
}
